package org.sprogram.utils
{

    /**
     * 产生随机数等随机操作
     */
    public final class Random
    {
        /**
         * 大写
         */
        public static const UPPERCASE:String = "uppercase";

        /**
         * 小写
         */
        public static const LOWERCASE:String = "lowercase";

        // --------------------------------------------------------------------
        // Properties (Get and Set)
        // --------------------------------------------------------------------

        /**
         * 获取Bool
         */
        public static function get boolean():Boolean
        {
            return Math.random() < .5;
        }

        /**
         * 获取正负波动值
         */
        public static function get wave():int
        {
            return Math.random() < .5 ? -1 : 1;
        }

        /**
         * 获取颜色 0(0x000000) - 16777216(0xFFFFFF).
         */
        public static function get color():uint
        {
            return Math.random() * 16777216;
        }

        /**
         * 获取整数 0 - num.
         */
        public static function integer(num:int):int
        {
            return Math.random() * num;
        }

        /**
         * 获取浮点数 0 - num
         */
        public static function number(num:int):Number
        {
            return Math.random() * num;
        }

        /**
         * 获取其中一个参数 char("a", "b", "c", ...);
         */
        public static function char(... args):String
        {
            return args[int(Math.random() * args.length)];
        }

        /**
         * 产生一个长度为num的字符串
         * 字符串产生的范围为0-9,A-Z,a-z
         */
        public static function string(num:int):String
        {
            for (var i:uint = 0, src:String = ""; i < num; i++)
            {
                src += charRanges("0", "9", "A", "Z", "a", "z");
            }
            return src;
        }

        /**
         * 产生n1-n2范围的整数
         */
        public static function intRange(n1:int, n2:int):int
        {
            return Math.random() * (n2 - n1) + n1;
        }

        /**
         * 产生n1-n2范围的浮点数
         */
        public static function numRange(n1:Number, n2:Number):Number
        {
            return Math.random() * (n2 - n1) + n1;
        }

        /**
         * 产生s1-s2范围的字符
         */
        public static function charRange(s1:String, s2:String):String
        {
            var n1:uint = s1.charCodeAt(0), n2:uint = s2.charCodeAt(0);
            return String.fromCharCode(int(Math.random() * (n2 - n1)) + n1);
        }

        /**
         * 在范围内(两两一对)获取一个数字
         */
        public static function intRanges(... args):int
        {
            var r1:int = (Math.random() * args.length) * 0.5;

            r1 = r1 * 2;

            var n1s:int = args[r1].charCodeAt(0);

            var n2s:int = args[r1 + 1].charCodeAt(0);

            var r:int   = Math.random() * (n2s - n1s) + n1s;

            return r;
        }

        /**
         * 在范围内(两两一对)获取一个浮点数
         */
        public static function numRanges(... args):Number
        {
            var r1:int = (Math.random() * args.length) * 0.5;

            r1 = r1 * 2;

            var n1s:int  = args[r1].charCodeAt(0);

            var n2s:int  = args[r1 + 1].charCodeAt(0);

            var r:Number = Math.random() * (n2s - n1s) + n1s;

            return r;
        }

        /**
         * 在范围内(两两一对)获取一个字符
         */
        public static function charRanges(... args):String
        {
            var r1:int = (Math.random() * args.length) * 0.5;

            r1 = r1 * 2;

            var n1s:int = args[r1].charCodeAt(0);

            var n2s:int = args[r1 + 1].charCodeAt(0) + 1;

            var r:int   = Math.random() * (n2s - n1s) + n1s;

            return String.fromCharCode(r);
        }

        /**
         * 获取num个字符在args范围内(两两一对)
         */
        public static function strRanges(num:uint, ... args):String
        {
            var src:String = "";

            while (num-- > 0)
            {
                var r1:int = (Math.random() * args.length) * 0.5;

                r1 = r1 * 2;

                var n1s:int = args[r1].charCodeAt(0);

                var n2s:int = args[r1 + 1].charCodeAt(0) + 1;

                var r:int   = Math.random() * (n2s - n1s) + n1s;

                src += String.fromCharCode(r);
            }
            return src;
        }

        /**
         * 在范围内(两两一对)获取一个字符
         */
        public static function colorRanges(... args):uint
        {
            return intRange(args[0], args[1] + 1) << 16 + intRange(args[2], args[3] + 1) << 8 + intRange(args[4], args[5] + 1);
        }

        /**
         * 将arr打乱顺序返回 modifyOriginal?true在原数组修改:false在副本数组修改
         */
        public static function disorder(arr:Array, modifyOriginal:Boolean = false):Array
        {
            if (arr != null)
            {
                if (!modifyOriginal)
                {
                    arr = arr.concat();
                }

                var len:uint = arr.length;
                var cache:Object;
                var ti:uint;


                for (var i:uint = 0; i < len; i++)
                {
                    ti = int(Math.random() * len);

                    // Swaps elements.
                    cache = arr[i];
                    arr[i] = arr[ti];
                    arr[ti] = cache;
                }

                while (--i >= 0)
                {
                    ti = int(Math.random() * len);

                    // Swaps elements.
                    cache = arr[i];
                    arr[i] = arr[ti];
                    arr[ti] = cache;
                }
            }

            return arr;
        }

        public static function takeOut(num:uint, arr:Array):Array
        {
            var newArr:Array = new Array(num);
            for (var i:uint = 0; i < num; i++)
            {
                newArr.push(arr.splice(int(Math.random() * arr.length)), 1);
            }
            return newArr;
        }

        /**
         * 随机从原数组中取出指定个数的元素，并且在原数组中删除它们
         */
        public static function find(arr:Array, num:uint):Array
        {
            var newArr:Array = disorder(arr);

            if (newArr != null)
            {
                return newArr.slice(0, num);
            }

            return newArr;
        }

        /**
         * 从start起按step的增速返回有num个数字的数组
         */
        public static function integerArray(num:int, start:int = 0, disorder:Boolean = true, step:int = 1):Array
        {
            if (num <= 0)
            {
                return [];
            }

            if (start < 0)
            {
                start = 0;
            }

            var arr:Array = new Array(num);

            for (var i:int = 0; i < num; i++)
            {
                arr[i] = i * step + start;
            }

            if (disorder)
            {
                return Random.disorder(arr);
            }
            else
            {
                return arr;
            }
        }

        /**
         * 随机fIndex-tIndex范围内元素的顺序
         */
        public static function hasRangeOfDisorder(totalArr:Array, fIndex:int, tIndex:int):Array
        {
            var tempArr:Array;
            if (totalArr != null && totalArr.length > 0 && totalArr.length >= tIndex
                && tIndex > fIndex && fIndex >= 0 && tIndex > 0)
            {
                tempArr = totalArr.s new Array(tIndex - fIndex);
                for (var i:int = 0; i < tempArr.length; i++) 
                {
                    tempArr[i] = totalArr[i + fIndex];
                }

                tempArr = disorder(tempArr);

                for (var j:int = 0; j < tempArr.length; j++)
                {
                    totalArr[j + fIndex] = tempArr[j];
                }
            }

            return totalArr;
        }
    }
}
